package com.bsg.upm.util;

import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.Date;

/**
 * 自定义比较器<br/>
 * 可以对int，float，double，long，Date以及它们对应的封装类进行比较<br/>
 * 数据为null时，默认排序规则是对null进行排序，null时表示最小，升序时显示在前，降序时显示在后。<br/>
 * 可以通过设置sortNull来修改对null的排序规则<br/>
 * 
 * @author HCK
 *
 */
public class AutoComparator implements Comparator<Object> {

	/**
	 * 排序方式：升序
	 */
	public static final String SORT_ASC = "asc";
	/**
	 * 排序方式：降序
	 */
	public static final String SORT_DESC = "desc";

	/**
	 * 对null进行排序，null时表示最小，升序时显示在前，降序时显示在后
	 */
	public static final String SORTNULL1 = "1";
	/**
	 * 不对null进行排序，无论是升序还是降序null总是显示在前面
	 */
	public static final String SORTNULL2 = "2";
	/**
	 * 不对null进行排序，无论是升序还是降序null总是显示在前面后面
	 */
	public static final String SORTNULL3 = "3";

	/**
	 * 排序字段
	 */
	private String sortField;
	/**
	 * 排序方式：默认升序
	 */
	private String sortOrder = SORT_ASC;
	/**
	 * NULL排序规则：默认对null进行排序，null时表示最小，升序时显示在前，降序时显示在后
	 */
	private String sortNull = SORTNULL1;

	/**
	 * 自定义比较器构造方法
	 * 
	 * @param sortField
	 *            排序字段
	 */
	public AutoComparator(String sortField) {
		this.sortField = sortField;
	}

	/**
	 * 自定义比较器构造方法
	 * 
	 * @param sortField
	 *            排序字段
	 * @param sortOrder
	 *            排序方式
	 */
	public AutoComparator(String sortField, String sortOrder) {
		this.sortField = sortField;
		this.sortOrder = sortOrder;
	}

	/**
	 * 获取排序字段
	 * 
	 * @return
	 */
	public String getSortField() {
		return sortField;
	}

	/**
	 * 设置排序字段
	 * 
	 * @param sortField
	 *            排序字段
	 */
	public void setSortField(String sortField) {
		this.sortField = sortField;
	}

	/**
	 * 获取排序方式
	 *
	 * @return sortOrder 排序方式
	 */
	public String getSortOrder() {
		return sortOrder;
	}

	/**
	 * 设置排序方式
	 *
	 * @param sortOrder
	 *            排序方式
	 */
	public void setSortOrder(String sortOrder) {
		this.sortOrder = sortOrder;
	}

	/**
	 * 获取NULL排序规则
	 *
	 * @return sortNull NULL排序规则
	 */
	public String getSortNull() {
		return sortNull;
	}

	/**
	 * 设置NULL排序规则
	 *
	 * @param sortNull
	 *            NULL排序规则
	 */
	public void setSortNull(String sortNull) {
		this.sortNull = sortNull;
	}

	/**
	 * 重写比较方法
	 */
	public int compare(Object arg0, Object arg1) {
		// 如果排序字段为空，则返回
		if (sortField == null || sortField.trim().equals("")) {
			return 0;
		}
		try {

			Field field = null;
			// java反射获取排序字段属性
			try {
				field = arg0.getClass().getDeclaredField(sortField);
			} catch (Exception e) {
				field = arg0.getClass().getSuperclass().getDeclaredField(sortField);
			}
			if (field != null) {
				// 设置属性是可以访问的
				field.setAccessible(true);

				// 获取属性值
				Object obj0 = field.get(arg0);
				Object obj1 = field.get(arg1);

				// 对null的排序处理
				switch (sortNull) {
				// 对null进行排序，null时表示最小，升序时显示在前，降序时显示在后
				case SORTNULL1:
					if (sortOrder.equals(SORT_ASC)) {
						if (obj0 == null && obj1 != null) {
							return -1;
						} else if (obj0 != null && obj1 == null) {
							return 1;
						} else if (obj0 == null && obj1 == null) {
							return 0;
						}
					} else if (sortOrder.equals(SORT_DESC)) {
						if (obj0 == null && obj1 != null) {
							return 1;
						} else if (obj0 != null && obj1 == null) {
							return -1;
						} else if (obj0 == null && obj1 == null) {
							return 0;
						}
					}
					break;
				// 不对null进行排序，无论是升序还是降序null总是显示在前面
				case SORTNULL2:
					if (obj0 == null && obj1 != null) {
						return -1;
					} else if (obj0 != null && obj1 == null) {
						return 1;
					} else if (obj0 == null && obj1 == null) {
						return 0;
					}
					break;
				// 不对null进行排序，无论是升序还是降序null总是显示在前面后面
				case SORTNULL3:
					if (obj0 == null && obj1 != null) {
						return 1;
					} else if (obj0 != null && obj1 == null) {
						return -1;
					} else if (obj0 == null && obj1 == null) {
						return 0;
					}
					break;
				}

				// 获取属性类型
				String typeName = field.getGenericType().toString();

				switch (typeName) {
				case "class java.lang.String":
					if (sortOrder.equals(SORT_ASC)) {
						return ((String) obj0).compareTo((String) obj1);
					} else if (sortOrder.equals(SORT_DESC)) {
						return ((String) obj1).compareTo((String) obj0);
					}
					break;
				case "class java.lang.Integer":
					if (sortOrder.equals(SORT_ASC)) {
						return (Integer) obj0 - (Integer) obj1;
					} else if (sortOrder.equals(SORT_DESC)) {

						return (Integer) obj1 - (Integer) obj0;
					}
					break;
				case "class java.lang.Float":
					if (sortOrder.equals(SORT_ASC)) {
						return (Float) obj0 - (Float) obj1 >= 0 ? 1 : -1;
					} else if (sortOrder.equals(SORT_DESC)) {
						return (Float) obj1 - (Float) obj0 >= 0 ? 1 : -1;
					}
					break;
				case "class java.lang.Double":
					if (sortOrder.equals(SORT_ASC)) {
						return (Double) obj0 - (Double) obj1 >= 0 ? 1 : -1;
					} else if (sortOrder.equals(SORT_DESC)) {
						return (Double) obj1 - (Double) obj0 >= 0 ? 1 : -1;
					}
					break;
				case "class java.lang.Long":
					if (sortOrder.equals(SORT_ASC)) {
						return (Long) obj0 - (Long) obj1 >= 0 ? 1 : -1;
					} else if (sortOrder.equals(SORT_DESC)) {
						return (Long) obj1 - (Long) obj0 >= 0 ? 1 : -1;
					}
					break;
				case "class java.util.Date":
					if (sortOrder.equals(SORT_ASC)) {
						return ((Date) obj0).compareTo((Date) obj1);
					} else if (sortOrder.equals(SORT_DESC)) {
						return ((Date) obj1).compareTo((Date) obj0);
					}
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return 0;
	}
}
